﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Media.Media3D;
using System.Windows.Media.Imaging;
using System.ComponentModel;
using System.Collections.ObjectModel;

using HelixToolkit.Wpf;
using EQEmu.Display3D;
using EQEmu.Grids;
using EQEmu.Database;

namespace EQEmu.Grids.Display3D
{
    public class GridsDisplay3D : IViewConstrainer, IDisposable
    {
        private GeometryModel3D _waypointModel;
        private GeometryModel3D _waypointPauseModel;
        private ViewConstraints _constraints = null;
        private Model3D _model = new Model3DGroup();
        private Grid _currentGrid;

        public GridsDisplay3D()
        {
            MeshBuild();
        }

        public void ShowGrid(Grid grid)
        {
            Model3DGroup group = Model as Model3DGroup;
            if (_currentGrid != null)
            {
                _currentGrid.GridEntriesChanged -= grid_GridEntriesChanged;
                _currentGrid.GridValue.PropertyChanged -= GridValue_PropertyChanged;
            }
            _currentGrid = grid;
            Model3DCollection collection = new Model3DCollection();

            foreach (var c in group.Children.ToArray())
            {
                group.Children.Remove(c);
            }

            int i = 0;
            foreach (var wp in grid.Entries)
            {
                GeometryModel3D model = null;
                if (wp.pause > 0)
                {
                    model = GetWaypointPauseModel();
                }
                else
                {
                    model = GetWaypointModel();
                }

                Transform3DGroup transforms = new Transform3DGroup();
                Transform3D headingRotate = new RotateTransform3D()
                {
                    CenterX = wp.x,
                    CenterY = wp.y,
                    CenterZ = wp.z,
                    Rotation = new AxisAngleRotation3D(
                        new Vector3D(0, 0, -1), Functions.HeadingToDegrees(wp.heading))
                };
                transforms.Children.Add(new TranslateTransform3D(wp.x, wp.y, wp.z));
                transforms.Children.Add(headingRotate);
                model.Transform = transforms;
                collection.Add(model);

                //create the connection arrow
                if (grid.GridValue.WanderType != EQEmu.grid.WanderTypes.Random &&
                    grid.GridValue.WanderType != EQEmu.grid.WanderTypes.RandomNearest10Waypoints)
                {
                    if (wp != grid.Entries.Last())
                    {
                        var builder = new MeshBuilder();
                        var nextWp = grid.Entries.ElementAt(i + 1);
                        builder.AddArrow(new Point3D(wp.x, wp.y, wp.z), new Point3D(nextWp.x, nextWp.y, nextWp.z), 1.0);
                        collection.Add(new GeometryModel3D(builder.ToMesh(), Materials.White));
                    }
                }
                i++;
            }

            grid.GridEntriesChanged += grid_GridEntriesChanged;
            grid.GridValue.PropertyChanged += GridValue_PropertyChanged;

            foreach (Model3D model in collection)
            {
                group.Children.Add(model);
            }  
        }

        void GridValue_PropertyChanged(object sender, PropertyChangedEventArgs e)
        {
            if (_currentGrid != null)
            {
                ShowGrid(_currentGrid);
            }
        }
        
        void grid_GridEntriesChanged(object sender, GridEntriesChangedEventArgs e)
        {
            if (_currentGrid != null)
            {
                ShowGrid(_currentGrid);
            }
        }

        private GeometryModel3D GetWaypointModel()
        {
            return _waypointModel.CloneCurrentValue();
        }

        private GeometryModel3D GetWaypointPauseModel()
        {
            return _waypointPauseModel.CloneCurrentValue();
        }

        private void MeshBuild()
        {
            MeshBuilder builder = new MeshBuilder();
            builder.AddBox(new Point3D(0, 0, 0), 2, 2, 2);
            builder.AddArrow(new Point3D(0, 0, 0), new Point3D(0, 3, 0), 0.5, 1);
            _waypointModel = new GeometryModel3D(builder.ToMesh(), Materials.White);  

            builder = new MeshBuilder();
            builder.AddBox(new Point3D(0, 0, 0), 2, 2, 2);
            builder.AddArrow(new Point3D(0, 0, 0), new Point3D(0, 3, 0), 0.5, 1);
            _waypointPauseModel = new GeometryModel3D(builder.ToMesh(), Materials.Red);              
        }
        
        public void UpdateView(ViewConstraints constraints)
        {
            _constraints = constraints;
        }

        public Model3D Model
        {
            get
            {
                return _model;
            }
        }

        protected virtual void Dispose(bool disposeall)
        {
            if (_currentGrid != null)
            {
                _currentGrid.GridEntriesChanged -= this.grid_GridEntriesChanged;
                _currentGrid.GridValue.PropertyChanged -= this.GridValue_PropertyChanged;
            }
        }

        public void Dispose()
        {
            Dispose(true);
        }
    }
}
